<?php


namespace models\Business;


use models\DAO\AddressModel;
use models\Exception\Business\AddressException;
use models\Exception\DAO\ModelDriverException;
use models\Exception\DAO\ModelException;
use models\Exception\DAO\ModelReflectionException;
use models\Exception\DAO\ModelSqlException;
use models\Exception\Service\ServiceException;
use models\Exception\Transformer\TransformerException;
use models\Service\AddressService;
use Yaf\Registry;

class Address
{
    /**
     * 删除地址
     * @param array $parameters
     * @throws AddressException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function deleteAddress($parameters = [])
    {
        try {
            if (!isset($parameters['id']) || empty($parameters['id']))
                throw new AddressException(AddressException::ADDRESS_ID_IS_EMPTY, AddressException::ADDRESS_ID_IS_EMPTY_NO);

            if (isset($parameters['from_api']) && $parameters['from_api'] === true) {
                try {
                    $address = AddressService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                        ['field' => 'id', 'op' => 'eq', 'data' => $parameters['id']],
                        ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                    ]]);
                } catch (ModelException $e) {
                    throw new AddressException(AddressException::ADDRESS_DENIED, AddressException::ADDRESS_DENIED_NO);
                }
            }

            AddressService::getInstance()->delete($parameters['id']);
        } catch (AddressException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        }
    }

    /**
     * 编辑地址
     * @param array $parameters
     * @return array|mixed|null
     * @throws AddressException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function editAddress($parameters = [])
    {
        try {
            if (!isset($parameters['id']) || empty($parameters['id']))
                throw new AddressException(AddressException::ADDRESS_ID_IS_EMPTY, AddressException::ADDRESS_ID_IS_EMPTY_NO);

            $address = null;
            if (isset($parameters['from_api']) && $parameters['from_api'] === true) {
                $address = AddressService::getInstance()->getOne($parameters['id']);
                if ($address['member_id'] != Registry::get('jwt_info')->id)
                    throw new AddressException(AddressException::ADDRESS_DENIED, AddressException::ADDRESS_DENIED_NO);
            } else
                $address = AddressService::getInstance()->getOne($parameters['id']);

            $update_arr = [];
            if (isset($parameters['is_default']) && (is_null($address) ||
                    (isset($address['is_default']) && $address['is_default'] != $parameters['is_default']))) {
                if ($parameters['is_default'] == 1) {
                    // 已经存在默认地址时，将旧的默认地址取消掉
                    try {
                        $rules = [['field' => 'id', 'op' => 'ne', 'data' => $parameters['id']],
                            ['field' => 'is_default', 'op' => 'eq', 'data' => 1]];
                        if (isset($parameters['from_api']) && $parameters['from_api'] === true)
                            array_push($rules, ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]);

                        $default_address = AddressService::getInstance()->getOne([
                            'groupOp' => 'AND', 'rules' => $rules]);
                        if ($default_address && $parameters['is_default'] == 1) {
                            AddressService::getInstance()->update(['is_default' => 0], $default_address['id']);
                        }
                    } catch (\Exception $e) {

                    }
                }
                $update_arr['is_default'] = $parameters['is_default'];
            }

            if (isset($parameters['province']) && (is_null($address) ||
                    (isset($address['province']) && $address['province'] != $parameters['province'])))
                $update_arr['province'] = $parameters['province'];

            if (isset($parameters['city']) && (is_null($address) ||
                    (isset($address['city']) && $address['city'] != $parameters['city'])))
                $update_arr['city'] = $parameters['city'];

            if (isset($parameters['ares']) && (is_null($address) ||
                    (isset($address['ares']) && $address['ares'] != $parameters['ares'])))
                $update_arr['ares'] = $parameters['ares'];

            if (isset($parameters['street']) && (is_null($address) ||
                    (isset($address['street']) && $address['street'] != $parameters['street'])))
                $update_arr['street'] = $parameters['street'];

            if (isset($parameters['address']) && (is_null($address) ||
                    (isset($address['location']) && $address['location'] != $parameters['address'])))
                $update_arr['location'] = $parameters['address'];

            if (isset($parameters['mobile']) && (is_null($address) ||
                    (isset($address['mobile']) && $address['mobile'] != $parameters['mobile'])))
                $update_arr['mobile'] = $parameters['mobile'];

            if (isset($parameters['name']) && (is_null($address) ||
                    (isset($address['name']) && $address['name'] != $parameters['name'])))
                $update_arr['name'] = $parameters['name'];

            if (isset($parameters['zipcode']) && (is_null($address) ||
                    (isset($address['zipcode']) && $address['zipcode'] != $parameters['zipcode'])))
                $update_arr['zipcode'] = $parameters['zipcode'];

            if (isset($parameters['stats']))
                $update_arr['stats'] = $parameters['stats'];

            $address = AddressService::getInstance()->getOne($parameters['id']);
            if (!empty($update_arr))
                $address = AddressService::getInstance()->update($update_arr, $parameters['id']);

            return $address;
        } catch (AddressException $e) {
            throw $e;
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new AddressException(AddressException::ADDRESS_EDIT_FAILURE, AddressException::ADDRESS_EDIT_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new AddressException(AddressException::ADDRESS_IS_NOT_EXISTS, AddressException::ADDRESS_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 获取收货地址列表
     * @param array $parameters
     * @return array|mixed
     * @throws AddressException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws ServiceException
     * @throws TransformerException
     */
    static public function getAddressList($parameters = [])
    {
        try {
            $rules = $condition = [];

            if (isset($parameters['id'])) {
                if (is_array($parameters['id']))
                    array_push($rules, ['field' => 'id', 'op' => 'in', 'data' => implode(",", $parameters['id'])]);
                else
                    array_push($rules, ['field' => 'id', 'op' => 'eq', 'data' => $parameters['id']]);
            }
            if (isset($parameters['is_default']))
                array_push($rules, ['field' => 'is_default', 'op' => 'eq', 'data' => $parameters['is_default']]);

            if (isset($parameters['member_id']))
                array_push($rules, ['field' => 'member_id', 'op' => 'eq', 'data' => $parameters['member_id']]);

            if (isset($parameters['from_api']) && $parameters['from_api'] === true)
                array_push($rules, ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id]);

            if (isset($parameters['from_api']) && $parameters['from_api'] === true)
                array_push($rules, ['field' => 'stats', 'op' => 'eq', 'data' => 1]);

            if (!empty($rules))
                $condition = ['groupOp' => 'And', 'rules' => $rules];

            $address_list = AddressService::getInstance()->getList(
                isset($parameters['page']) ? $parameters['page'] : 1,
                isset($parameters['page_size']) ? $parameters['page_size'] : 10,
                isset($parameters['sort']) ? $parameters['sort'] : 'desc',
                'is_default, ' . (isset($parameters['order']) ? $parameters['order'] : 'id'),
                $condition
            );

            if (empty($address_list['data']) && isset($parameters['from_api']) && $parameters['from_api'] === true)
                throw new AddressException(AddressException::ADDRESS_IS_NOT_EXISTS, AddressException::ADDRESS_IS_NOT_EXISTS_NO);

            $address_list = Member::getMembersByModules($address_list, false);

            return $address_list;
        } catch (ModelDriverException $e) {
            throw $e;
        } catch (ModelException $e) {
            if ($e->getCode() == ModelException::DATA_NOT_EXISTS_NO)
                throw new AddressException(AddressException::ADDRESS_IS_NOT_EXISTS, AddressException::ADDRESS_IS_NOT_EXISTS_NO);
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (ServiceException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    /**
     * 创建收货地址
     * @param $parameters
     * @return array
     * @throws AddressException
     * @throws ModelDriverException
     * @throws ModelException
     * @throws ModelReflectionException
     * @throws ModelSqlException
     * @throws TransformerException
     */
    static public function createAddress($parameters)
    {
        // 已经存在默认地址时，将旧的默认地址取消掉
        try {
            $default_address = AddressService::getInstance()->getOne([
                'groupOp' => 'AND', 'rules' => [
                    ['field' => 'member_id', 'op' => 'eq', 'data' => Registry::get('jwt_info')->id],
                    ['field' => 'is_default', 'op' => 'eq', 'data' => 1]]]);
            if ($default_address && $parameters['is_default'] == 1) {
                AddressService::getInstance()->update(['is_default' => 0], $default_address['id']);
            }
        } catch (\Exception $e) {

        }

        try {
            // $member_id = 0, $is_default = 0,
            // $province = "", $city = "", $area = "", street = "", $location = "",
            // $name = "", $zipcode = "", $mobile = ""
            return AddressService::getInstance()->create(
                Registry::get('jwt_info')->id, $parameters['is_default'],
                $parameters['province'], $parameters['city'], $parameters['area'], $parameters['street'],
                $parameters['address'], $parameters['name'],
                isset($parameters['zipcode']) ? $parameters['zipcode'] : 0,
                $parameters['mobile'], 1
            );
        } catch (ModelDriverException $e) {
            if ($e->getCode() == ModelDriverException::DRIVER_EXCEPTION_MSG_NO)
                throw new AddressException(AddressException::ADDRESS_CREATE_FAILURE, AddressException::ADDRESS_CREATE_FAILURE_NO);
            throw $e;
        } catch (ModelException $e) {
            throw $e;
        } catch (ModelReflectionException $e) {
            throw $e;
        } catch (ModelSqlException $e) {
            throw $e;
        } catch (TransformerException $e) {
            throw $e;
        }
    }

    static public function getAddress($parameters)
    {
        if (!isset($parameters['id']) || empty($parameters['id']))
            throw new AddressException(AddressException::ADDRESS_ID_IS_EMPTY, AddressException::ADDRESS_ID_IS_EMPTY_NO);

        if (isset($parameters['stats']))
            $address_info = AddressService::getInstance()->getOne(['groupOp' => 'AND', 'rules' => [
                ['field' => 'id', 'op' => 'eq', 'data' => $parameters['id']],
                ['field' => 'stats', 'op' => 'eq', 'data' => $parameters['stats']]]]);
        else
            $address_info = AddressService::getInstance()->getOne($parameters['id']);
        if (empty($address_info))
            throw new AddressException(AddressException::ADDRESS_IS_NOT_EXISTS, AddressException::ADDRESS_IS_NOT_EXISTS_NO);
        return $address_info;
    }

    /**
     * @param array $modules_list
     * @return array
     */
    static public function getAddressByModules($modules_list = [])
    {
        $address = $address_id_info_arr = [];
        try {
            $address_id_arr = array_column($modules_list['data'], 'address_id');
            $address_id_arr = array_filter(array_unique($address_id_arr));

            if (count($address_id_arr) == 1)
                $address['data'][] = Address::getAddress(['id' => implode('', $address_id_arr)]);
            else if (count($address_id_arr) > 1)
                $address = Address::getAddressList(['page' => 1, 'page_size' => count($address_id_arr),
                                                    'sort' => 'desc', 'order' => 'id', 'id' => $address_id_arr]);

            $address_id_info_arr = array_column($address['data'], null, 'id');
        } catch (\Exception $e) {

        } finally {
            foreach ($modules_list['data'] as $k => $v) {
                $modules_list['data'][$k]['address_info'] = isset($address_id_info_arr[$v['address_id']]) ? $address_id_info_arr[$v['address_id']] : [];
            }
            return $modules_list;
        }
    }
}
